#include "net_include.h"

//name of the host name
#define NAME_LENGTH 80

int gethostname(char*,size_t);

void PromptForHostName( char *my_name, char *host_name, char *server_name, size_t max_len); 

int main(int argc, char** argv)
{
    struct sockaddr_in    name;
    struct sockaddr_in    send_addr;
    struct sockaddr_in    from_addr;
    socklen_t             from_len;
    struct hostent        h_ent; //this data type is used to represent an entry in the hosts database
    struct hostent        *p_h_ent;
    char                  host_name[NAME_LENGTH] = {'\0'};//host name of the server machine
    char                  my_name[NAME_LENGTH] = {'\0'}; //host name of the local machine
    long                  host_num;
    int                   ss,sr;
    fd_set                mask;
    fd_set                dummy_mask,temp_mask;
    int                   bytes;
    int                   num;
    struct timeval        timeout;
	
    //buffers
    //char                  mess_buf[MAX_MESS_LEN];
	char				  buf_msgs[WIN_SIZE][PACK_SIZE - MSG_HEAD_SIZE]; //buffer for reading file data
	char				  buf_send[BUF_SEND_SIZE]; //buffer for sending message to server
    //char                  input_buf[80];
    char 				  buf_recv[BUF_RECV_SIZE]; //buffer for receiving message from server

	//variables to handle cmd line input
	int i = 0;
	double loss_rate = 0.0;	//loss_rate_percent
	char* source_file_name; //source file name
	char* dest_file_name;   //dest file name
	char* server_name;		//server name or comp_name
	char deli = '@'; 		//delimiter of the argv[3]
	
	//variables about sliding window.
	//sequence number start from zero.
	int send_start=0;			//the sequence num of the 1st message in the current window.
	int send_end=WIN_SIZE-1;	//the sequence num of the last message in the current window.

	//message header
	MSG_HEAD send_msg_head;

	/* create send and receive sockets;
	 * bind ports;
	 */
    sr = socket(AF_INET, SOCK_DGRAM, 0);  /* socket for receiving (udp) */
    if (sr<0) {
        perror("ncp receive socket fail of creating");
        exit(1);
    }

    name.sin_family = AF_INET; 
    name.sin_addr.s_addr = INADDR_ANY; 
    name.sin_port = htons(CLI_PORT);

	//bind port to client
    if ( bind( sr, (struct sockaddr *)&name, sizeof(name) ) < 0 ) {
        perror("Ucast: bind");
        exit(1);
    }
 
    ss = socket(AF_INET, SOCK_DGRAM, 0); /* socket for sending (udp) */
    if (ss<0) {
        perror("ncp send socket fail of creating");
        exit(1);
    }
    
	/*
	 * handle cmd line input
	 */
	if(argc != 4)
	{
		perror("please input all of 3 input parameter\n");
		exit(1);
	}

	loss_rate = atoi(argv[1]) / 100.0; //get the loss rate
	source_file_name = argv[2];        //get the source file name
	dest_file_name = argv[3];          //get the dest file name
	
	for(i=0; argv[3][i]!='\0'; i++)    //find delimiter '@'
	{
		if(argv[3][i]==deli) 
		{
			argv[3][i] = '\0';
			break;
		}
	}
	
	dest_file_name = argv[3];
    server_name = &argv[3][i+1];	
	
	/*
	 * get the host names
	 */
    PromptForHostName(my_name,host_name, server_name ,NAME_LENGTH);
	
    p_h_ent = gethostbyname(host_name); //get host info of server
    if ( p_h_ent == NULL ) {
        printf("Ucast: gethostbyname error.\n");
        exit(1);
    }

    memcpy( &h_ent, p_h_ent, sizeof(h_ent));
	//h_addr_list is the vector of addresses for the host. 
    memcpy( &host_num, h_ent.h_addr_list[0], sizeof(host_num) );
	printf("host num is: %ld\n", host_num); //comment later ????
	
    send_addr.sin_family = AF_INET;
    send_addr.sin_addr.s_addr = host_num; 
    send_addr.sin_port = htons(SERV_PORT);

    FD_ZERO( &mask );
    FD_ZERO( &dummy_mask );
    FD_SET( sr, &mask );
    FD_SET( (long)0, &mask ); /* stdin */
    for(;;)
    {
        temp_mask = mask;
        timeout.tv_sec = 3; //change to 3 secs
		timeout.tv_usec = 0; //micro seconds
        num = select( FD_SETSIZE, &temp_mask, &dummy_mask, &dummy_mask, &timeout);
        if (num > 0) {
            if ( FD_ISSET( sr, &temp_mask) ) {
                from_len = sizeof(from_addr);
                bytes = recvfrom( sr, buf_recv, sizeof(buf_recv), 0, 
						(struct sockaddr *)&from_addr, &from_len );
                //buf_recv[bytes] = '\0';//delete ???
                printf( "Received : %s\n", buf_recv ); //comment later??????????
            }else if( FD_ISSET(0, &temp_mask) ) {
                bytes = read( 0, buf_msgs, sizeof(buf_msgs) );
                //buf_msgs[bytes] = '\0';//delete ???
                printf( "There is an input: %s\n", buf_msgs ); //comment later ????????????
				for(i=0; i<WIN_SIZE; i++)
				{   
					//head + data = 1024 bytes ??????????
					//fill in msg header
					send_msg_head.msg_type = 2;
					send_msg_head.seq_num = send_start;
					send_msg_head.ip = host_num; //does it work ?
					send_msg_head.port = SERV_PORT;
					send_msg_head.len = MSG_HEAD_SIZE;

					//memcpy header to buf_send, we can't copy 
					//  the "send_msg_head" dicrctly, we copy each member 
					//  of send_msg_head respectly instead to make sure 
					//  the size of header is the same as MSG_HEAD_SIZE
					memcpy(&buf_send[0], &send_msg_head.msg_type, sizeof(send_msg_head.msg_type));
					memcpy(&buf_send[1], &send_msg_head.seq_num, sizeof(send_msg_head.seq_num));
					memcpy(&buf_send[5], &send_msg_head.ip, sizeof(send_msg_head.ip));
					memcpy(&buf_send[9], &send_msg_head.port, sizeof(send_msg_head.port));
					memcpy(&buf_send[11], &send_msg_head.len, sizeof(send_msg_head.len));

					
					//memcpy file data to buf_send
					memcpy(&buf_send[15], &buf_msgs[i][0], PACK_SIZE - MSG_HEAD_SIZE);
                	
					//send message to server
					sendto( ss, buf_send, strlen(buf_send), 0, 
                    	(struct sockaddr *)&send_addr, sizeof(send_addr) );
					////sendto( ss, input_buf, strlen(input_buf), 0, 
                    ////	(struct sockaddr *)&send_addr, sizeof(send_addr) );

				}
            }
	} else {
		printf(".");
		fflush(0);
        }
    }

    return 0;

}

//get host names
void PromptForHostName( char *my_name, char *host_name, char* server_name ,size_t max_len ) {

    char *c;

    gethostname(my_name, max_len );	//get the localhost name
	strncpy(host_name, server_name, strlen(server_name)); //get the host name of server
   
   	//trim "\n" and "\r" if they exists at the end of host name
    c = strchr(host_name,'\n');
    if ( c ) *c = '\0';
    c = strchr(host_name,'\r');
    if ( c ) *c = '\0';
}
